package extend

import (
	"bufio"
	systemConfig "gin-worked/app/system/config"
	"gin-worked/app/system/model"
	"io/ioutil"
	"os"
	"regexp"
	"strings"
)

func CreateFile(info model.DataSheet, list []model.DataSheet) error {
	dir, _ := os.Getwd()
	modelPath := dir + "/app/system/model"            //创建模型路径
	servicePath := dir + "/app/system/service"        //创建业务路径
	validatePath := dir + "/app/system/validate"      //创建验证层路径
	controllerPath := dir + "/app/system/controllers" //创建controller路径
	routerPath := dir + "/app/system/router.go"       //路由路径

	title := systemConfig.RemoveFirstUnderscore(info.Title)

	tableName := systemConfig.Case2Camel(title)

	err := createModel(modelPath, tableName, list) //创建模型

	if err != nil {
		return err
	}

	err1 := createService(servicePath, tableName, list) //创建业务层
	if err1 != nil {
		return err
	}

	err2 := createValidate(validatePath, tableName, list) //创建验证层
	if err2 != nil {
		return err
	}

	err3 := createController(controllerPath, tableName, list) //创建controller
	if err3 != nil {
		return err
	}

	errRouter := createRouter(routerPath, tableName, title)
	if errRouter != nil {
		return errRouter
	}

	return nil
}

// 创建模型
func createModel(path string, name string, list []model.DataSheet) error {

	var str string
	tableName := systemConfig.ToLowerFirst(name) //首字母转小写

	str += "package model \n\n" +
		"import ( \n" +
		"    \"" + "gin-worked/dao" + "\"" +
		"\n) " +
		"\n\ntype " + name + "  struct { \n"

	for _, value := range list {

		var types string
		switch value.Type {
		case "int":
			types = "int"
			break
		case "tinyint":
			types = "int"
			break
		case "bigint":
			types = "int"
			break
		default:
			types = "string"
		}
		str += "\n    " + systemConfig.Case2Camel(value.Title) + " " + types + "  `gorm:\"column(" + value.Title + ")\" json:\"" + value.Title + "\"`"
	}

	str += "\n}" +
		"\n\n\n // 添加数据 \n" +
		"func " + name + "Add(data *" + name + " ) (int, error){" +
		"\n    err := dao.Db.Create(&data).Error\n" +
		"    return data.Id, err \n}\n\n\n" +
		"// 详情 \n" +
		"func " + name + "Info(data *" + name + ",field []string)(" + name + ",error){\n" +
		"    var " + tableName + " " + name + " \n" +
		"    err := dao.Db.Select(field).Where(data).First(&" + tableName + ").Error\n" +
		"    return " + tableName + ", err\n" +
		"}\n\n\n " +
		"//编辑" +
		"\nfunc " + name + "Edit(data *" + name + ", content map[string]interface{})error{\n" +
		"    err := dao.Db.Model(&data).Updates(content).Error\n" +
		"    return err" +
		"\n}\n\n\n" +
		"//获取列表 \n" +
		"func " + name + "List(data *" + name + ", field []string, order string, offset int, limit int) ([]" + name + ", error){\n" +
		"    var " + tableName + " []" + name + "\n" +
		"    err := dao.Db.Select(field).Where(data).Offset(offset).Limit(limit).Order(order).Find(&" + tableName + ").Error\n" +
		"    return " + tableName + ", err\n" +
		"}\n\n\n" +
		"//总条数 \n" +
		"func " + name + "Total(data *" + name + ")int64{\n" +
		"    var count int64\n" +
		"    dao.Db.Model(&" + name + "{}).Where(data).Count(&count)\n" +
		"    return count\n" +
		"}\n\n\n" +
		"//删除\n" +
		"func " + name + "Del(data *" + name + ")error{\n" +
		"    var  " + tableName + " " + name + "\n" +
		"    err := dao.Db.Where(data).Delete(&" + tableName + ").Error\n" +
		"    return err\n" +
		"}"

	err := ioutil.WriteFile(path+"/"+tableName+".go", []byte(str), 0777)
	if err != nil {
		return err
	}

	return nil
}

// 创建业务层
func createService(path string, name string, list []model.DataSheet) error {
	tableName := systemConfig.ToLowerFirst(name) //首字母转小写
	var str string
	str += "package service \n\n" +
		"import (\n" +
		"    \"" + "gin-worked/app/system/model" + "\"\n" +
		"    \"" + "strconv" + "\"\n" +
		"    \"" + "time" + "\"\n)\n\n\n" +
		"   type " + name + "ListApi struct{\n" +
		"   List interface{}\n" +
		"   Total int" +
		"\n}"
	//新增
	var addStr string
	var addConvertStr string
	var addDataStr = "data := &model." + name + "{\n"
	//详情
	var addInfoDataStr = "data := &model." + name + "{\n"
	var addFieldStr = "    filed:= []string{"
	var addConvertInfoStr string
	var editDataStr = "    var content = map[string]interface{}{"

	for _, value := range list {
		if value.Title != "id" {
			//新增数据 组装
			addStr += value.Title + " string,"

			switch value.Type {
			case "int":
				addConvertStr += "        " + value.Title + "Es, _ := strconv.Atoi(" + value.Title + ")\n"
				addDataStr += "    " + systemConfig.Case2Camel(value.Title) + ":" + value.Title + "Es,\n"
				editDataStr += "    \"" + value.Title + "\":" + value.Title + "Es,"
				continue
			case "tinyint":
				addConvertStr += "        " + value.Title + "Es, _ := strconv.Atoi(" + value.Title + ")\n"
				addDataStr += "    " + systemConfig.Case2Camel(value.Title) + ":" + value.Title + "Es,\n"
				editDataStr += "    \"" + value.Title + "\":" + value.Title + "Es,"
				continue
			case "bigint":
				addConvertStr += "        " + value.Title + "Es, _ := strconv.Atoi(" + value.Title + ")\n"
				addDataStr += "    " + systemConfig.Case2Camel(value.Title) + ":" + value.Title + "Es,\n"
				editDataStr += "    \"" + value.Title + "\":" + value.Title + "Es,"
				continue
			}
			addDataStr += "        " + systemConfig.Case2Camel(value.Title) + ":" + value.Title + ",\n"
			editDataStr += "    \"" + value.Title + "\":" + value.Title + "," //编辑

		} else {
			addConvertInfoStr += value.Title + "Es, _ := strconv.Atoi(" + value.Title + ")\n"
			addInfoDataStr += "    " + systemConfig.Case2Camel(value.Title) + ":" + value.Title + "Es,\n"
		}
		addFieldStr += "    \"" + value.Title + "\","

	}
	editDataStr = strings.TrimSuffix(editDataStr, ",") //去除结尾的字符
	editDataStr += "}"

	addDataStr += "\n    " +
		"}\n   "
	addInfoDataStr += "\n    }\n"
	addFieldStr += "}\n"
	str += "\n//添加 \nfunc " + name + "Add(" + addStr + ")Res{\n" +
		"    " + addConvertStr + "\n" +
		"    " + addDataStr + "\n" +
		"    res, err := model." + name + "Add(data) \n" +
		"    if err != nil{\n" +
		"        return Res{0,err.Error(),\"\"}\n" +
		"    }\n" +
		"    return Res{1,\"" + "success" + "\",res}\n" +
		"} \n\n\n " +
		"//详情 \n" +
		" func " + name + "Info(id string)Res{\n" +
		"    " + addConvertInfoStr + "\n" +
		"    " + addInfoDataStr + "" +
		"\n    " + addFieldStr + "\n" +
		"    info,err :=model." + name + "Info(data,filed)\n" +
		"    if err != nil {\n" +
		"         return Res{0,err.Error(),\"\"}\n" +
		"    }\n" +
		"    return Res{1, \"success\" ,info}\n" +
		"}" +
		"\n\n\n//列表\n" +
		"func " + name + "List(limit string,offset string)Res{\n" +
		"    limitEs, _ := strconv.Atoi(limit)\n" +
		"    offsetEs,_ :=strconv.Atoi(offset)\n    " +
		"    //条件组装\n" +
		"    data := &model." + name + "{}\n" +
		"    " + addFieldStr +
		"\n    order:= \"" + "id ASC" + "\"\n" +
		"    list, err :=model." + name + "List(data,filed,order,offsetEs,limitEs)\n" +
		"    if err != nil{\n" +
		"        return Res{0,err.Error(),\"\"}\n" +
		"    }\n" +
		"    total := model." + name + "Total(data)\n" +
		"    content := " + name + "ListApi{\n" +
		"       Total:int(total),\n" +
		"       List:list,\n" +
		"    }\n" +
		"    return Res{1,\"success\",content}\n" +
		"}\n\n\n" +
		"//编辑\n" +
		"func " + name + "Edit(id string," + addStr + ") Res{\n" +
		"    " + addConvertInfoStr + addConvertStr + addInfoDataStr + "\n" +
		"    " + editDataStr + "\n" +
		"    err:=model." + name + "Edit(data,content)\n" +
		"    if err != nil{\n" +
		"        return Res{0,err.Error(),\"\"}\n" +
		"    }\n" +
		"    return Res{1,\"" + "success" + "\",\"\"}\n" +
		"}\n\n\n" +
		"//删除\n" +
		"func " + name + "Del(id string)Res{\n" +
		"     " + addConvertInfoStr + addInfoDataStr + "\n" +
		"     err:=model." + name + "Del(data)\n" +
		"    if err != nil{\n" +
		"        return Res{0,err.Error(),\"\"}\n" +
		"    }\n" +
		"   return Res{1,\"" + "success" + "\",\"\"}" +
		"\n}"

	addStr = strings.TrimSuffix(addStr, ",")

	err := ioutil.WriteFile(path+"/"+tableName+".go", []byte(str), 0777)
	if err != nil {
		return err
	}
	return nil
}

// 创建验证层
func createValidate(path string, name string, list []model.DataSheet) error {
	var str string
	tableName := systemConfig.ToLowerFirst(name) //首字母转小写

	var addStr string
	var infoStr string
	for _, value := range list {
		if value.Title != "id" && value.IsValidation == 1 {
			addStr += "    " + systemConfig.Case2Camel(value.Title) + "   string `json:\"" + value.Title + "\" binding:\"required\"`\n"
		} else if value.Title == "id" {
			infoStr += "    " + systemConfig.Case2Camel(value.Title) + "   string `json:\"" + value.Title + "\" binding:\"required\"`\n"
		}
	}

	str += "package validate\n\n" +
		"//新增验证\n" +
		"type " + name + "Add  struct {\n" +
		"" + addStr + "}\n\n\n" +
		"//详情验证\n" +
		"type " + name + "Info  struct {\n" +
		"" + infoStr + "}\n\n\n" +
		"//编辑\n" +
		"type " + name + "Edit struct {\n" +
		addStr + infoStr + "}\n\n\n" +
		"type " + name + "List struct {\n" +
		"    Limit string `json:\"limit\" binding:\"required\"`" +
		"\n    Offset string `json:\"offset\" binding:\"required\"`" +
		"\n}"

	err := ioutil.WriteFile(path+"/"+tableName+".go", []byte(str), 0777)
	if err != nil {
		return err
	}

	return nil
}

func createController(path string, name string, list []model.DataSheet) error {
	var str string
	tableName := systemConfig.ToLowerFirst(name) //首字母转小写
	abbrName := systemConfig.GetUppercaseLetters(name)

	var addStr string
	var infoStr string
	for _, value := range list {
		if value.Title != "id" {
			addStr += "param[\"" + systemConfig.Case2Camel(value.Title) + "\"],"
		} else {
			infoStr += "param[\"" + systemConfig.Case2Camel(value.Title) + "\"]"
		}
	}
	addStr = strings.TrimSuffix(addStr, ",") //去除结尾的字符
	str += "package controllers\n\n\n" +
		"import(\n" +
		"    \"gin-worked/app/system/service\"\n" +
		"    \"gin-worked/app/system/validate\"\n" +
		"    \"gin-worked/work\"\n" +
		"    \"github.com/gin-gonic/gin\"" + "\n" +
		")\n\n\n" +
		"type " + name + "Controller struct{}" +
		"\n\n\n" +
		"//列表\n" +
		"func (" + abbrName[0] + " " + name + "Controller) List(c *gin.Context){\n" +
		"    var list validate." + name + "List\n" +
		"    if err := c.ShouldBind(&list); err != nil {\n" +
		"        work.ReturnResult(c, 0, err.Error(), \"\")\n" +
		"        return\n" +
		"    }\n    " +
		"    param := c.MustGet(\"params\").(map[string]string)\n" +
		"    res := service." + name + "List(param[\"Limit\"],param[\"Offset\"])\n" +
		"    work.ReturnResult(c, res.Code, res.Msg, res.Data)\n" +
		"     return\n}" +
		"\n\n\n" +
		"//添加\n" +
		"func (" + abbrName[0] + " " + name + "Controller) Add(c *gin.Context){\n" +
		"    var add validate." + name + "List\n" +
		"    if err := c.ShouldBind(&add); err != nil {\n" +
		"        work.ReturnResult(c, 0, err.Error(), \"\")\n" +
		"        return\n" +
		"    }\n" +
		"    param := c.MustGet(\"params\").(map[string]string)\n" +
		"    res:=service." + name + "Add(" + addStr + ")\n" +
		"    work.ReturnResult(c, res.Code, res.Msg, res.Data)\n" +
		"    return\n" +
		"}\n\n\n" +
		"//详情\n" +
		"func ( " + abbrName[0] + " " + name + "Controller) Info(c *gin.Context){\n" +
		"    var info validate." + name + "Info\n" +
		"    if err := c.ShouldBind(&info); err != nil {\n" +
		"        work.ReturnResult(c, 0, err.Error(), \"\")\n" +
		"        return\n" +
		"    }\n" +
		"    param := c.MustGet(\"params\").(map[string]string)\n" +
		"    res:=service." + name + "Info(" + infoStr + ")\n" +
		"    work.ReturnResult(c, res.Code, res.Msg, res.Data)\n" +
		"    return\n" +
		"}" +
		"\n\n\n//编辑\n" +
		"func ( " + abbrName[0] + " " + name + "Controller) Edit(c *gin.Context){\n" +
		"    var edit validate." + name + "Info\n" +
		"    if err := c.ShouldBind(&edit); err != nil {\n" +
		"        work.ReturnResult(c, 0, err.Error(), \"\")\n" +
		"        return\n" +
		"    }\n" +
		"    param := c.MustGet(\"params\").(map[string]string)\n" +
		"    res:=service." + name + "Edit(" + infoStr + "," + addStr + ")\n" +
		"    work.ReturnResult(c, res.Code, res.Msg, res.Data)\n" +
		"    return\n" +
		"}" +
		"\n\n\n//删除\n" +
		"func ( " + abbrName[0] + " " + name + "Controller)  Del(c *gin.Context){\n" +
		"    var info validate." + name + "Info\n" +
		"    if err := c.ShouldBind(&info); err != nil {\n" +
		"        work.ReturnResult(c, 0, err.Error(), \"\")\n" +
		"        return\n" +
		"    }\n" +
		"    param := c.MustGet(\"params\").(map[string]string)\n" +
		"    res:=service." + name + "Del(" + infoStr + ")\n" +
		"    work.ReturnResult(c, res.Code, res.Msg, res.Data)\n" +
		"    return\n" +
		"}"

	err := ioutil.WriteFile(path+"/"+tableName+".go", []byte(str), 0777)
	if err != nil {
		return err
	}

	return nil
}

// 创建后台路由
func createRouter(path string, name string, routerName string) error {
	reg := regexp.MustCompile(`^[_ ]*`)
	routerName = reg.ReplaceAllString(routerName, "")
	str := "    //" + name + "模块管理\n        system.POST(\"" + routerName + "/list\", Controllers." + name + "Controller{}.List)//" + name + "列表\n" +
		"        system.POST(\"" + routerName + "/add\", Controllers." + name + "Controller{}.Add)//" + name + "添加\n" +
		"        system.POST(\"" + routerName + "/info\", Controllers." + name + "Controller{}.Info)//" + name + "详情\n" +
		"        system.POST(\"" + routerName + "/edit\", Controllers." + name + "Controller{}.Edit)//" + name + "编辑\n" +
		"        system.POST(\"" + routerName + "/del\", Controllers." + name + "Controller{}.Del)//" + name + "删除\n\n    }\n}"
	file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, 0777)

	systemConfig.UnsetFileContent(path, 4)

	// 从文件末尾开始写入
	writer := bufio.NewWriter(file)
	_, err = writer.WriteString(str + "\n")
	if err != nil {
		return err
	}

	err = writer.Flush()
	if err != nil {
		return err
	}
	return nil
}
